import * as fs from 'fs-extra';
import * as path from 'path';
import matter from 'gray-matter';
import { DocumentInfo, DocumentChunk, RefreshStats, RefreshTask } from './types';
import { VectorSearchService } from './vector-search';
import { BriefingService } from './briefing-service';
import { TaskManager } from './task-manager';
import { AliBailianConfig } from './ali-bailian-service';

export class DocumentManager {
  private vectorService: VectorSearchService;
  private briefingService: BriefingService;
  private metadataPath: string;
  private taskManager: TaskManager;

  constructor(aliBailianConfig?: AliBailianConfig) {
    this.vectorService = new VectorSearchService(aliBailianConfig);
    this.briefingService = new BriefingService(aliBailianConfig);
    this.metadataPath = path.join(process.cwd(), '.cb-document-helper');
    this.taskManager = TaskManager.getInstance();
  }

  // 启动异步文档刷新任务
  async startRefreshDocumentsAsync(directoryPath: string, forceUpdate: boolean = false): Promise<string> {
    const task = this.taskManager.createTask(directoryPath, forceUpdate);
    
    // 启动后台任务
    this.executeRefreshTask(task.id).catch(error => {
      console.error(`Background task ${task.id} failed:`, error);
      this.taskManager.failTask(task.id, error.message);
    });
    
    return task.id;
  }

  // 获取任务状态
  getTaskStatus(taskId: string): RefreshTask | undefined {
    return this.taskManager.getTask(taskId);
  }

  // 获取所有任务
  getAllTasks(): RefreshTask[] {
    return this.taskManager.getAllTasks();
  }

  // 执行刷新任务的内部方法
  private async executeRefreshTask(taskId: string): Promise<void> {
    const task = this.taskManager.getTask(taskId);
    if (!task) {
      throw new Error(`Task ${taskId} not found`);
    }

    try {
      this.taskManager.updateTaskStatus(taskId, 'running');

      const stats: RefreshStats = {
        totalFiles: 0,
        updatedFiles: 0,
        skippedFiles: 0,
        chunksCreated: 0,
        briefingsGenerated: 0,
      };

      // 确保元数据目录存在
      await fs.ensureDir(this.metadataPath);

      // 查找所有markdown文件
      const markdownFiles = await this.findMarkdownFiles(task.directoryPath);
      stats.totalFiles = markdownFiles.length;

      // 更新任务进度
      this.taskManager.updateTaskProgress(taskId, {
        processedFiles: 0,
        totalFiles: markdownFiles.length,
      });

      for (let i = 0; i < markdownFiles.length; i++) {
        const filePath = markdownFiles[i];
        
        try {
          // 更新当前处理的文件
          this.taskManager.updateTaskProgress(taskId, {
            processedFiles: i,
            totalFiles: markdownFiles.length,
            currentFile: filePath,
          });

          const shouldUpdate = await this.shouldUpdateFile(filePath, task.forceUpdate);
          
          if (!shouldUpdate) {
            stats.skippedFiles++;
            continue;
          }

          // 读取并处理文档
          const documentInfo = await this.readDocument(filePath);
          
          // 创建文档块
          const chunks = await this.createChunks(documentInfo);
          stats.chunksCreated += chunks.length;

          // 生成或更新嵌入向量
          for (const chunk of chunks) {
            await this.vectorService.addChunk(chunk);
          }

          // 生成文档简介
          await this.briefingService.generateBriefing(documentInfo);
          stats.briefingsGenerated++;

          // 更新文件时间戳
          await this.updateFileTimestamp(filePath);
          stats.updatedFiles++;

          console.error(`Processed: ${filePath}`);
        } catch (error) {
          console.error(`Error processing ${filePath}:`, error);
        }
      }

      // 完成任务
      this.taskManager.updateTaskProgress(taskId, {
        processedFiles: markdownFiles.length,
        totalFiles: markdownFiles.length,
      });
      
      this.taskManager.completeTask(taskId, stats);

    } catch (error) {
      this.taskManager.failTask(taskId, error instanceof Error ? error.message : String(error));
      throw error;
    }
  }

  async refreshDocuments(directoryPath: string, forceUpdate: boolean = false): Promise<RefreshStats> {
    const stats: RefreshStats = {
      totalFiles: 0,
      updatedFiles: 0,
      skippedFiles: 0,
      chunksCreated: 0,
      briefingsGenerated: 0,
    };

    // 确保元数据目录存在
    await fs.ensureDir(this.metadataPath);

    // 查找所有markdown文件
    const markdownFiles = await this.findMarkdownFiles(directoryPath);
    stats.totalFiles = markdownFiles.length;

    for (const filePath of markdownFiles) {
      try {
        const shouldUpdate = await this.shouldUpdateFile(filePath, forceUpdate);
        
        if (!shouldUpdate) {
          stats.skippedFiles++;
          continue;
        }

        // 读取并处理文档
        const documentInfo = await this.readDocument(filePath);
        
        // 创建文档块
        const chunks = await this.createChunks(documentInfo);
        stats.chunksCreated += chunks.length;

        // 生成或更新嵌入向量
        for (const chunk of chunks) {
          await this.vectorService.addChunk(chunk);
        }

        // 生成文档简介
        await this.briefingService.generateBriefing(documentInfo);
        stats.briefingsGenerated++;

        // 更新文件时间戳
        await this.updateFileTimestamp(filePath);
        stats.updatedFiles++;

        console.error(`Processed: ${filePath}`);
      } catch (error) {
        console.error(`Error processing ${filePath}:`, error);
      }
    }

    return stats;
  }

  private async findMarkdownFiles(dirPath: string): Promise<string[]> {
    const files: string[] = [];
    
    const entries = await fs.readdir(dirPath, { withFileTypes: true });
    
    for (const entry of entries) {
      const fullPath = path.join(dirPath, entry.name);
      
      if (entry.isDirectory()) {
        // 跳过特定目录
        if (entry.name.startsWith('.') || entry.name === 'node_modules') {
          continue;
        }
        files.push(...await this.findMarkdownFiles(fullPath));
      } else if (entry.isFile() && entry.name.endsWith('.md')) {
        files.push(fullPath);
      }
    }
    
    return files;
  }
  private async shouldUpdateFile(filePath: string, forceUpdate: boolean): Promise<boolean> {
    if (forceUpdate) {
      return true;
    }

    try {
      const stat = await fs.stat(filePath);
      const timestampFile = path.join(this.metadataPath, 'timestamps.json');
      
      let timestamps: Record<string, number> = {};
      if (await fs.pathExists(timestampFile)) {
        timestamps = await fs.readJson(timestampFile);
      }

      const lastUpdatedTimestamp = timestamps[filePath];
      if (!lastUpdatedTimestamp) {
        return true;
      }

      // 使用时间戳比较，更加鲁棒
      const fileModifiedTimestamp = stat.mtime.getTime();
      return fileModifiedTimestamp > lastUpdatedTimestamp;
    } catch {
      return true;
    }
  }
  private async updateFileTimestamp(filePath: string): Promise<void> {
    const timestampFile = path.join(this.metadataPath, 'timestamps.json');
    
    let timestamps: Record<string, number> = {};
    if (await fs.pathExists(timestampFile)) {
      timestamps = await fs.readJson(timestampFile);
    }

    // 保存时间戳而不是 ISO 字符串，更加鲁棒
    timestamps[filePath] = Date.now();
    await fs.writeJson(timestampFile, timestamps, { spaces: 2 });
  }

  private async readDocument(filePath: string): Promise<DocumentInfo> {
    const content = await fs.readFile(filePath, 'utf-8');
    const parsed = matter(content);
    const stat = await fs.stat(filePath);

    return {
      filePath,
      content: parsed.content,
      frontMatter: parsed.data,
      lastModified: stat.mtime,
    };
  }

  private async createChunks(documentInfo: DocumentInfo): Promise<DocumentChunk[]> {
    const chunks: DocumentChunk[] = [];
    const lines = documentInfo.content.split('\n');
    const chunkSize = 500; // 每个块的最大字符数
    const overlapSize = 50; // 重叠字符数

    let currentChunk = '';
    let startLine = 0;
    let currentLine = 0;

    for (let i = 0; i < lines.length; i++) {
      const line = lines[i];
      
      if (currentChunk.length + line.length > chunkSize && currentChunk.length > 0) {
        // 创建当前块
        if (currentChunk.trim()) {
          chunks.push({
            id: `${documentInfo.filePath}:${startLine}-${currentLine}`,
            filePath: documentInfo.filePath,
            content: currentChunk.trim(),
            startLine: startLine + 1, // 1-indexed
            endLine: currentLine + 1,
          });
        }

        // 准备下一个块，包含重叠
        const overlap = currentChunk.slice(-overlapSize);
        currentChunk = overlap + '\n' + line;
        startLine = Math.max(0, currentLine - Math.floor(overlapSize / 20)); // 估算重叠行数
      } else {
        if (currentChunk) {
          currentChunk += '\n' + line;
        } else {
          currentChunk = line;
          startLine = i;
        }
      }
      currentLine = i;
    }

    // 添加最后一个块
    if (currentChunk.trim()) {
      chunks.push({
        id: `${documentInfo.filePath}:${startLine}-${currentLine}`,
        filePath: documentInfo.filePath,
        content: currentChunk.trim(),
        startLine: startLine + 1,
        endLine: currentLine + 1,
      });
    }

    return chunks;
  }
}
